﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HAC
{
    public class ClusterPairs
    {
        HashSet<ClusterPair> pairs = new HashSet<ClusterPair>();
        //record the mapping relationship between a cluster and the pairs containing it, to quickly locate the pairs need to be removed when two clusters are merged into one new cluster
        public static Dictionary<int, HashSet<ClusterPair>> cluster_pair_map = new Dictionary<int, HashSet<ClusterPair>>();
        //Given a cluster, add a new pair containing it
        public static void Update_Cluster_Pair_Map(int clusterid, ClusterPair pair)
        {
            HashSet<ClusterPair> pairs_map = null;
            if (cluster_pair_map.ContainsKey(clusterid))
            {
                pairs_map = cluster_pair_map[clusterid];
                pairs_map.Add(pair);
            }
            else
            {
                pairs_map = new HashSet<ClusterPair>();
                pairs_map.Add(pair);
                cluster_pair_map.Add(clusterid, pairs_map);
            }
        }

        /*If a pair whose distance is smaller than the given ShortOutDistance, return it immediately*/
        internal ClusterPair LowestDistancePair(float ShortCutDistance)
        {
            ClusterPair lowestDistancePair = null;
            if (pairs.Count >= 1)
            {
                lowestDistancePair = pairs.ElementAt(0);
                foreach (ClusterPair pair in pairs)
                {
                    if (pair.Distance < ShortCutDistance)
                    {
                        lowestDistancePair = pair;
                        break;
                    }
                    if (lowestDistancePair.Distance > pair.Distance)
                        lowestDistancePair = pair;
                }
            }
            return lowestDistancePair;
        }

        internal int Count
        {
            get { return pairs.Count; }
        }

        internal void AddPair(ClusterPair pair)
        {
            pairs.Add(pair);
            //at the meatime , need to update the related clusters information for the two clusters in the pair
            HAC.updateRelatedClustersOfOneCluster(pair.Cluster1.id, pair.Cluster2.id);
            HAC.updateRelatedClustersOfOneCluster(pair.Cluster2.id, pair.Cluster1.id);
            //at the meatime , need to update the related pairs information for the two clusters in the pair
            Update_Cluster_Pair_Map(pair.Cluster1.id, pair);
            Update_Cluster_Pair_Map(pair.Cluster2.id, pair);
        }

        internal void RemovePairsByOldClusters(Cluster cluster1, Cluster cluster2)
        {
            HashSet<ClusterPair> pairs_1 = cluster_pair_map[cluster1.id];
            HashSet<ClusterPair> pairs_2 = cluster_pair_map[cluster2.id];
            /*Although some pairs might be already removed before, we don't need to check this. If a pairs was removed from pairs before (i.e. not exist in pairs), then the Remove method of HashSet does nothing.*/
            foreach (ClusterPair pair in pairs_1)
            {
                pairs.Remove(pair);
            }
            foreach (ClusterPair pair in pairs_2)
            {
                pairs.Remove(pair);
            }
            //cluster1 and cluster2 are deprecated, so remove their information
            cluster_pair_map.Remove(cluster1.id);
            cluster_pair_map.Remove(cluster2.id);
        }
    }
}
